package cn.com.gzheroli.core.extend.sqlgen;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;


import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.jdbc.SQL;

import cn.com.gzheroli.core.common.entity.TableAndColumns;
import cn.com.gzheroli.core.extend.sqlgen.parse.ObjectParseUtil;
import cn.com.gzheroli.core.extend.sqlgen.parse.PageValueConvertRuleEnum;
import cn.com.gzheroli.core.extend.sqlgen.parse.vo.SqlRuleEnum;
import cn.com.gzheroli.core.util.DataUtils;
import cn.com.gzheroli.core.util.NameHandler;
import cn.com.gzheroli.core.util.JSONHelper;
import cn.com.gzheroli.core.util.StringUtil;

/**
 * 
 * @author 张代浩
 * @de
 * 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class HqlGenerateUtil {
	/** 时间查询符号 */
	private static final String END = "_end";
	private static final String BEGIN = "_begin";

	private static final SimpleDateFormat time = new SimpleDateFormat(
			"yyyy-MM-dd hh:mm:ss");

	/**
	 * 自动生成查询条件HQL 模糊查询 不带有日期组合
	 * 
	 * @param cq
	 * @param searchObj
	 * @throws Exception
	 */
	public static void installSql(SQL sql, Object searchObj) {
		installSql(sql,searchObj,null);

	}

	/**
	 * 自动生成查询条件HQL（扩展区间查询功能）
	 * 
	 * @param cq
	 * @param searchObj
	 * @param parameterMap
	 *            request参数集合，封装了所有查询信息
	 */
	public static void installSql(SQL sql, Object searchObj,
			Map<String, String[]> parameterMap) {
		installSqlJoinAlias(sql, searchObj, parameterMap, "");
	}

	/**
	 * 添加Alias别名的查询
	 * 
	 * @date 2014年1月19日
	 * @param cq
	 * @param searchObj
	 * @param parameterMap
	 * @param alias
	 */
	private static void installSqlJoinAlias(SQL sql, Object searchObj,
			Map<String, String[]> parameterMap, String alias) {
		PropertyDescriptor origDescriptors[] = PropertyUtils
				.getPropertyDescriptors(searchObj);
		String aliasName, name, type;
		for (int i = 0; i < origDescriptors.length; i++) {
			aliasName = (alias.equals("") ? "" : alias + ".")+ origDescriptors[i].getName();
			name = origDescriptors[i].getName();
			type = origDescriptors[i].getPropertyType().toString();
			try {
				if (judgedIsUselessField(name)|| !PropertyUtils.isReadable(searchObj, name)) {
					continue;
				}
				// 添加 判断是否有区间值
				String beginValue = null;
				String endValue = null;
				if (parameterMap != null&& parameterMap.containsKey(name + BEGIN)) {
					beginValue = parameterMap.get(name + BEGIN)[0].trim();
				}
				if (parameterMap != null&& parameterMap.containsKey(name + END)) {
					endValue = parameterMap.get(name + END)[0].trim();
				}

				Object value = PropertyUtils.getSimpleProperty(searchObj, name);
				// 根据类型分类处理
				if (type.contains("class java.lang")|| type.contains("class java.math")) {

					// for：查询拼装的替换
					if (value != null && !value.equals("")) {
						SqlRuleEnum rule = PageValueConvertRuleEnum.convert(value);

						if(SqlRuleEnum.LIKE.equals(rule)&&(!(value+"").contains("*"))){
							value="*%"+value+"%*";
						}

						value = PageValueConvertRuleEnum.replaceValue(rule,value);
						ObjectParseUtil.addSql(sql, aliasName, rule, value);
					} else if (parameterMap != null) {

						Object beginValue_=null , endValue_ =null;
						if ("class java.lang.Integer".equals(type)) {
							if(!"".equals(beginValue)&&null!=beginValue) {
								beginValue_ = Integer.parseInt(beginValue);
							}
							if(!"".equals(endValue)&&null!=endValue) {
								endValue_ =Integer.parseInt(endValue);
							}
						} else if ("class java.math.BigDecimal".equals(type)) {
							if(!"".equals(beginValue)&&null!=beginValue) {
								beginValue_ = new BigDecimal(beginValue);
							}
							if(!"".equals(endValue)&&null!=endValue) {
								endValue_ = new BigDecimal(endValue);
							}
						} else if ("class java.lang.Short".equals(type)) {
							if(!"".equals(beginValue)&&null!=beginValue) {
								beginValue_ =Short.parseShort(beginValue);
							}
							if(!"".equals(endValue)&&null!=endValue) {
								endValue_ =Short.parseShort(endValue);
							}
						} else if ("class java.lang.Long".equals(type)) {
							if(!"".equals(beginValue)&&null!=beginValue) {
								beginValue_ = Long.parseLong(beginValue);
							}
							if(!"".equals(endValue)&&null!=endValue) {
								endValue_ =Long.parseLong(endValue);
							}
						} else if ("class java.lang.Float".equals(type)) {
							if(!"".equals(beginValue)&&null!=beginValue) {
								beginValue_ = Float.parseFloat(beginValue);
							}
							if(!"".equals(endValue)&&null!=endValue) {
								endValue_ =Float.parseFloat(endValue);
							}
						}else{
							 beginValue_ = beginValue;
							 endValue_ = endValue;
						}
						ObjectParseUtil.addSql(sql, aliasName,SqlRuleEnum.GE, beginValue_);
						ObjectParseUtil.addSql(sql, aliasName,SqlRuleEnum.LE, endValue_);
					}

					// for：查询拼装的替换
				} else if ("class java.util.Date".equals(type)) {
					//QueryTimeFormat format = origDescriptors[i].getReadMethod().getAnnotation(QueryTimeFormat.class);
					SimpleDateFormat userDefined = null;
					
					userDefined =DataUtils.datetimeFormat;
					if (StringUtils.isNotBlank(beginValue)) {
						if (userDefined != null) {
							//cq.ge(aliasName, userDefined.parse(beginValue));
							sql.WHERE(aliasName+">="+userDefined.parse(beginValue));
						} else if (beginValue.length() == 19) {
							//cq.ge(aliasName, time.parse(beginValue));
							sql.WHERE(aliasName+">="+time.parse(beginValue));
						} else if (beginValue.length() == 10) {
							//cq.ge(aliasName,time.parse(beginValue + " 00:00:00"));
							sql.WHERE(aliasName+">="+time.parse(beginValue + " 00:00:00"));
						}
					}
					if (StringUtils.isNotBlank(endValue)) {
						if (userDefined != null) {
							//cq.ge(aliasName, userDefined.parse(beginValue));
							sql.WHERE(aliasName+">="+userDefined.parse(beginValue));
						} else if (endValue.length() == 19) {
							//cq.le(aliasName, time.parse(endValue));
							sql.WHERE(aliasName+"<="+time.parse(endValue));
						} else if (endValue.length() == 10) {
							// 对于"yyyy-MM-dd"格式日期，因时间默认为0，故此添加" 23:23:59"并使用time解析，以方便查询日期时间数据
							//cq.le(aliasName, time.parse(endValue + " 23:23:59"));
							sql.WHERE(aliasName+"<="+time.parse(endValue + " 23:23:59"));
						}
					}
					if (isNotEmpty(value)) {
						//cq.eq(aliasName, value);
						sql.WHERE(aliasName+"='"+value+"'");
					}
				} else if (!StringUtil.isJavaClass(origDescriptors[i].getPropertyType())) {
					Object param = PropertyUtils.getSimpleProperty(searchObj,
							name);
					if (( isNotEmpty(param)&& itIsNotAllEmpty(param))) {
						// 如果是实体类,创建别名,继续创建查询条件

						// for：用户反馈
						//cq.createAlias(aliasName,aliasName.replaceAll("\\.", "_"));
						// ------------end--Author:JueYue Date:20140521 for：用户反馈
						installSqlJoinAlias(sql, param,parameterMap,aliasName);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}



	private static boolean judgedIsUselessField(String name) {
		return "class".equals(name) || "ids".equals(name)
				|| "page".equals(name) || "rows".equals(name)
				|| "sort".equals(name) || "order".equals(name);
	}

	/**
	 * 判断是不是空
	 */
	public static boolean isNotEmpty(Object value) {
		return value != null && !"".equals(value);
	}

	/**
	 * 判断这个类是不是所以属性都为空
	 * 
	 * @param param
	 * @return
	 */
	private static boolean itIsNotAllEmpty(Object param) {
		boolean isNotEmpty = false;
		try {
			PropertyDescriptor origDescriptors[] = PropertyUtils
					.getPropertyDescriptors(param);
			String name;
			for (int i = 0; i < origDescriptors.length; i++) {
				name = origDescriptors[i].getName();
				if ("class".equals(name)|| !PropertyUtils.isReadable(param, name)) {
					continue;
				}
				if (Map.class.isAssignableFrom(origDescriptors[i].getPropertyType())) {
					Map<?, ?> map = (Map<?, ?>) PropertyUtils.getSimpleProperty(param, name);
					if (map != null && map.size() > 0) {
						isNotEmpty = true;
						break;
					}
				} else if (Collection.class.isAssignableFrom(origDescriptors[i]
						.getPropertyType())) {
					Collection<?> c = (Collection<?>) PropertyUtils.getSimpleProperty(param, name);
					if (c != null && c.size() > 0) {
						isNotEmpty = true;
						break;
					}
				} else if (StringUtil.isNotEmpty(PropertyUtils.getSimpleProperty(param, name))) {
					isNotEmpty = true;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return isNotEmpty;
	}


//	--author：龙金波 ------start---date：20150628--------for：sql高级查询器参数的sql组装
	/**
	 * @author ljb
	 * 根据对象拼装sql 
	 * TODO 结合DataRule
	 * @param list
	 * @param tab格式化
	 * @return
	 */
	public static String getSql(List<QueryCondition> list,String tab,Class claszz){
		String tableName = NameHandler.getTableName(claszz.getSimpleName());
		StringBuffer sb=new StringBuffer();
		sb.append(" 1=1 ");
		for(QueryCondition c :list){
			String column = invokeFindColumn(tableName,c.getField());
			String type = invokeFindType(claszz,c.getField());
			c.setType(type);
			c.setField(column);
			sb.append(tab+c);sb.append("\r\n");
			if(c.getChildren()!=null){
				
				List list1= JSONHelper.toList(c.getChildren(), QueryCondition.class);
				sb.append(tab);
				sb.append(c.getRelation()+"( ");
				sb.append(getSql(list1,tab+"\t",claszz));
				sb.append(tab+")\r\n");
			}
		}
		return sb.toString();
	}

//	--author：龙金波 ------end---date：20150628--------for：sql组装
	/**
	 * 根据字段名称,获取字段的类型字符串
	 * return: java.lang.Integer
	 */
	public static String invokeFindType(Class clazz,String field_name){
		String type=null;
		Field field;
		try {
			field = clazz.getDeclaredField(field_name);
			if(field!=null){
				type=field.getType().getSimpleName();
			}
		} catch (Exception e) {
			return type;
		}
		return type;
	}
	/**
	 * 根据字段名称返回hibernate映射数据库字段名
	 * @param clazz
	 * @param field_name	字段名称
	 * @return
	 */
	public static String invokeFindColumn(String tableName,String field_name){
		String columnName = NameHandler.getColumnName(field_name);
		 return columnName;
	}
//	--author：陈璞 ------end---date：20150612--------for：sql组装
	
	
	
	/**
	 * 获取装载数据权限条件的HQL
	 * @return cq
	 * @param cq
	 * @param searchObj
	 */
	public static SQL getDataAuthorConditionHql(SQL sql, Object searchObj,String tableName) {
		//Map<String, TSDataRule> ruleMap = getRuleMap();
		PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(searchObj);
		String aliasName, name, type;
		for (int i = 0; i < origDescriptors.length; i++) {
			aliasName = origDescriptors[i].getName();
			aliasName=invokeFindColumn(tableName,aliasName);
			name = origDescriptors[i].getName();
			type = origDescriptors[i].getPropertyType().toString();
			try {
				if (judgedIsUselessField(name) || !PropertyUtils.isReadable(searchObj, name)) {
					continue;
				}
				// 如果规则包含这个属性
				Object value = PropertyUtils.getSimpleProperty(searchObj, name);
				// 根据类型分类处理
				if (type.contains("class java.lang") || type.contains("class java.math")) {

					// for：查询拼装的替换
					if (value != null && !value.equals("")) {
						SqlRuleEnum rule = PageValueConvertRuleEnum.convert(value);
						value = PageValueConvertRuleEnum.replaceValue(rule, value);
						ObjectParseUtil.addSql(sql, aliasName, rule, value);
					}

					// for：查询拼装的替换
				} else if ("class java.util.Date".equals(type)) {
					SimpleDateFormat userDefined = null;
					userDefined=DataUtils.datetimeFormat;
					if (isNotEmpty(value)) {
						sql.WHERE(aliasName+"='"+value+"'");
					}
				} else if (!StringUtil.isJavaClass(origDescriptors[i].getPropertyType())) {
					Object param = PropertyUtils.getSimpleProperty(searchObj, name);
					if ( (isNotEmpty(param) && itIsNotAllEmpty(param))) {
						getDataAuthorConditionHql(sql, param,tableName);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return sql;
	}
}
